// 可变参数
# include <iostream>
# include <string>
#include <numeric>

template <typename... Args> //形参包 类型形参包
void test(const Args&... args) //形参包 函数参数包
{
    std::cout << ( ... + args ) << std::endl; //折叠表达式
}
// args 是函数形参包, Args 是类型形参包
// args 全部传入的参数, Args 所有参数的类型

// 模式匹配展开
template <typename... Args>
void print(const Args&... args)
{
    // (std::cout << arg0 << " ", 0), (std::cout << arg1 << " ", 0), (std::cout << arg2
    int _[] = { (std::cout << args << " ", 0)... }; //展开包
    std::cout << std::endl;
    (void)_; //避免编译器警告
    // std::cout << "size of Args: " << sizeof...(Args) << std::endl; //参数包大小
    // std::cout << "num of args: " << sizeof(_) / sizeof(int) << std::endl; //参数包大小
}

template <typename T, std::size_t N, typename... Args>
void f(const T (&array)[N], const Args&... index)
{
    print(array[index]...); //展开包
}
// const T (&array)[N] 数组引用
// print(array[0], array[1], array[2])


template <typename... Args, typename RT = std::common_type_t<Args...>>
RT sum(const Args&... args)
{
    RT _[]{ static_cast<RT>(args)... }; //展开包 1, 2, 3, 4, 5
    return std::accumulate(std::begin(_), std::end(_), RT{});
}
// std::common_type_t<Args...> 推导出所有参数的公共类型作为返回值类型
// std::accumulate 用于对数组进行累加

int main()
{
    print(1, 2.2, "three", std::string("four"));

    int arr[] = {10, 20, 30, 40, 50};
    f(arr, 0, 2, 4); //OK

    double result = sum(1, 2.2, 3, 4.4, 5); //RT 被推导为 double
    std::cout << result << std::endl;

    return 0;
}